﻿using SketchUpAPI.NET.Enums;
using SketchUpAPI.NET.SketchUp.Exception;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace SketchUpAPI.NET.Objects
{
    /// <summary>
    /// 边
    /// </summary>
    /// <remarks>对应 SketchUpAPI 中的 SUEdgeRef </remarks>
    public class Edge : DrawingElement
    {
        #region API 函数
        /// <summary>
        /// 创建边缘
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeCreate(out IntPtr edge, Point3D start, Point3D end);

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="edge"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeRelease(ref IntPtr edge);

        /// <summary>
        /// 获取与该边缘关联的曲线
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="curve"><see cref="Curve"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetCurve(IntPtr edge, out IntPtr curve);

        /// <summary>
        /// 获取边缘其实顶点
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="vertex"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetStartVertex(IntPtr edge, out IntPtr vertex);

        /// <summary>
        /// 获取边缘结束顶点
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="vertex"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetEndVertex(IntPtr edge, out IntPtr vertex);

        /// <summary>
        /// 设置软化
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="soft_flag"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeSetSoft(IntPtr edge, bool soft_flag);

        /// <summary>
        /// 是否软化
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="soft_flag"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetSoft(IntPtr edge, out bool soft_flag);

        /// <summary>
        /// 设置柔滑状态
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="smooth_flag"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeSetSmooth(IntPtr edge, bool smooth_flag);

        /// <summary>
        /// 获取柔滑状态
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="smooth_flag"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetSmooth(IntPtr edge, out bool smooth_flag);

        /// <summary>
        /// 获取关联的面个数
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetNumFaces(IntPtr edge, out long count);

        /// <summary>
        /// 获取全部关联的面
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="len"></param>
        /// <param name="faces"></param>
        /// <param name="realcount"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetFaces(IntPtr edge, long len, IntPtr[] faces, out long realcount);

        /// <summary>
        /// 获取边缘颜色
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="color"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetColor(IntPtr edge, out Color color);

        /// <summary>
        /// 设置颜色
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="color"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeSetColor(IntPtr edge, Color color);

        /// <summary>
        /// 获取应用变换后的长度
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="transform"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeGetLengthWithTransform(IntPtr edge, Transformation transform, out double length);

        /// <summary>
        /// 边是否在面的循环中反转
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="face"><see cref="Face"/></param>
        /// <param name="reversed"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUEdgeReversedInFace(IntPtr edge, IntPtr face, out bool reversed);
        #endregion

        /// <summary>
        /// 关联曲线
        /// </summary>
        public Curve Curve
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetCurve(Id, out IntPtr curve));
                return new Curve(curve);
            }
        }

        /// <summary>
        /// 关联的面
        /// </summary>
        public List<Face> Faces
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetNumFaces(Id, out long count));
                IntPtr[] pts = new IntPtr[count];
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetFaces(Id, count, pts, out long realcount));
                return pts.Select(i => new Face(i)).ToList();
            }
        }

        /// <summary>
        /// 起点
        /// </summary>
        public Vertex Start
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetStartVertex(Id, out IntPtr s));
                return new Vertex(s);
            }
        }

        /// <summary>
        /// 终点
        /// </summary>
        public Vertex End
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetEndVertex(Id, out IntPtr e));
                return new Vertex(e);
            }
        }

        /// <summary>
        /// 是否软化
        /// </summary>
        public bool IsSoft
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetSoft(Id, out bool s));
                return s;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeSetSoft(Id, value));
            }
        }

        /// <summary>
        /// 是否柔滑
        /// </summary>
        public bool IsSmooth
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetSmooth(Id, out bool s));
                return s;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeSetSmooth(Id, value));
            }
        }

        /// <summary>
        /// 边缘颜色
        /// </summary>
        public Color Color
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetColor(Id, out Color color));
                return color;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SUEdgeSetColor(Id, value));
            }
        }

        /// <summary>
        /// 创建一条边缘
        /// </summary>
        /// <param name="start">起点</param>
        /// <param name="end">终点</param>
        public Edge(Point3D start, Point3D end)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUEdgeCreate(out Id, start, end));
        }

        internal Edge(IntPtr id) : base(id) { }

        /// <summary>
        /// 是否在某个面的循环中被反转了方向
        /// </summary>
        /// <param name="face"></param>
        /// <returns></returns>
        public bool IsReversedInFace(Face face)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUEdgeReversedInFace(Id, face.Id, out bool reversed));
            return reversed;
        }

        /// <summary>
        /// 获取某个变换下的长度
        /// </summary>
        /// <param name="trans"></param>
        /// <returns></returns>
        public double GetLengthWithTransform(Transformation trans)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUEdgeGetLengthWithTransform(Id, trans, out double length));
            return length;
        }

        /// <summary>
        /// 如果Edge不关联到其他物件中，就应该在使用之后释放
        /// </summary>
        public override void Dispose()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUEdgeRelease(ref Id));
        }
    }
}